﻿using MediatR;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ORS.OrderRobot.Cache;
using ORS.OrderRobot.Service.Helper;
using ORS.OrderRobot.ServiceContracts;
using ORS.OrderRobot.ServiceContracts.Dtos;
using ORS.OrderRobot.ServiceContracts.ThridPartApi;

namespace ORS.OrderRobot.Service.Tasker
{
    /// <summary>
    /// 自动下单任务类
    /// </summary>
	public class AutoShoppingTasker : BackgroundRepeatTaskerBase
    {
        private int _guardUserIndex = 0;
        private readonly IServiceProvider _serviceProvider;
        private readonly ILogger<AutoShoppingTasker> _logger;
        private readonly IMediator _mediator;
        private readonly ICache _cache;
        private readonly IHubContext<MessageHub> _hubContext;
        private readonly ISystemConfigService _systemConfigService;
        private readonly AccountCacheManager _accountCacheManager;
        private readonly string _msgObj = "自动下单器";
        public AutoShoppingTasker(
            IServiceProvider serviceProvider,
            ILogger<AutoShoppingTasker> logger,
            IMediator mediator,
            ICache cache,
            IHubContext<MessageHub> hubContext,
            ISystemConfigService systemConfigService,
            AccountCacheManager accountCacheManager) :base(logger,serviceProvider)
        {
            _serviceProvider = serviceProvider;
            _logger = logger;
            _mediator = mediator;
            _cache = cache;
            _hubContext = hubContext;
            _systemConfigService = systemConfigService;
            _accountCacheManager = accountCacheManager;
        }
        public override string Key => "1";

        protected override string Name => nameof(AutoShoppingTasker);

        protected override async Task DoWorkAsync()
        {
            _logger.LogInformation("AutoShoppingTasker-DoWorkAsync进入");
            try
            {
                using var scope = _serviceProvider.CreateScope();
                var productService = scope.ServiceProvider.GetRequiredService<IThirdProductService>();

                var configDto = await _systemConfigService.GetConfigAsync();
                if (configDto.AutoShoppingTask.Disabled)
                {
                    _logger.LogWarning("自动下单任务被被禁用");
                    return;
                }
                var taskLock = await _cache.GetAsync<bool>(Consts.CacheKey.PurchaseLock);
                if (taskLock)
                {
                    await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = _msgObj, Action = "上一轮下单任务还在执行" });
                    return;
                }
                var productList = configDto.MointerProductInfos;
                if (productList == null || !productList.Any())
                {
                    await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = _msgObj, Action = "未配置目标商品", Type = Consts.ErrMsg });
                    _logger.LogError("未配置商品组");
                    return;
                }
                await _cache.SetAsync(Consts.CacheKey.PurchaseLock, true);
                if (configDto.AutoShoppingTask.IsNormalFlow)
                {
                    await NormalMode(productList);
                }
                else
                {
                    await GuardMode(productList);
                }
            }
            catch { }
            finally
            {
                _logger.LogInformation("AutoShoppingTasker-DoWorkAsync执行完成");
                await _cache.SetAsync(Consts.CacheKey.PurchaseLock, false);
            }
        }
        /// <summary>
        /// 延迟策略
        /// </summary>
        /// <param name="attempt"></param>
        /// <returns></returns>
        protected override async Task<TimeSpan> GetIntervalAsync(int attempt)
        {
            var configDto = await _systemConfigService.GetConfigAsync();
            var interval = configDto.AutoShoppingTask.Interval;
            var intervalUnit = configDto.AutoShoppingTask.IntervalUnit;
            return intervalUnit switch
            {
                TimeUnit.MillionSecond => TimeSpan.FromMilliseconds(interval),
                TimeUnit.Second => TimeSpan.FromSeconds(interval),
                TimeUnit.Minute => TimeSpan.FromMinutes(interval),
                _ => TimeSpan.FromSeconds(interval)
            };
        }
        /// <summary>
        /// 设置启动时间
        /// </summary>
        /// <returns></returns>
        protected override async Task<TimeOnly> GetTargetStartTimeAsync()
        {
            var configDto = await _systemConfigService.GetConfigAsync();
            return configDto.AutoShoppingTask.StartTime ?? new TimeOnly(06, 0);
        }
        /// <summary>
        /// 是否应该停止
        /// </summary>
        /// <returns></returns>
        protected override async Task<bool> ShouldStopAsync()
        {
            var configDto = await _systemConfigService.GetConfigAsync();
            var endTime = configDto.AutoShoppingTask.EndTime ?? new TimeOnly(18, 0);
            var now = DateTime.Now.China().TimeOfDay;
            return now > endTime.ToTimeSpan();
        }
        protected override async Task OnStartAsync()
        {
            await base.OnStartAsync();
            await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = $"{_msgObj} Id:{Id}" ,Action = "已启动"});
        }
        protected override async Task OnStopAsync()
        {
            await base.OnStopAsync();
            await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = $"{_msgObj} Id:{Id}", Action = "已停止" });
        }
        protected override async Task OnPauseAsync()
        {
            await base.OnPauseAsync();
            await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = $"{_msgObj} Id:{Id}", Action = "已暂停" });
        }

        protected override async Task OnResumeAsync()
        {
            await base.OnResumeAsync();
            await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = $"{_msgObj} Id:{Id}", Action = "已恢复" });
        }
        /// <summary>
        /// 常规模式
        /// </summary>
        /// <param name="productList"></param>
        /// <returns></returns>
        private async Task NormalMode(List<ProductInfo> productList)
        {
            await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = _msgObj, Action = "普通下单模式开始" });
            var tasks = productList.Select(async p =>
            {
                await _mediator.Publish(new PurchaseEvent(p.Id, p.Name));
            });
            await Task.WhenAll(tasks);
        }
        /// <summary>
        /// 哨兵模式
        /// </summary>
        /// <param name="productList"></param>
        /// <returns></returns>
        private async Task GuardMode(List<ProductInfo> productList)
        {
            using var scope = _serviceProvider.CreateScope();
            var accountLoginService = scope.ServiceProvider.GetRequiredService<IAccountLoginService>();
            var shoppingService = scope.ServiceProvider.GetRequiredService<IShoppingService>();

            await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = _msgObj, Action = "变态下单模式已开启" });
            var userList = await accountLoginService.GetLoginedAccounts();
            if (userList == null || !userList.Any())
            {
                await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = _msgObj, Action = "无已登录的用户列表",Type = Consts.ErrMsg });
                _logger.LogWarning("无已登录的用户列表,停止哨兵模式");
                return;
            }
            var boardingDto = await _accountCacheManager.GetAllBoarding();
            var sortedBoarding = boardingDto?.OrderBy(x => x.DepartureDate).Take(50).ToList() ?? new List<AccountBoardingDto>();
            var emailList = sortedBoarding.Select(x => x.Email).Where(email => userList.Contains(email)).ToList();
            var noOrderEmails = new List<string>();
            for (int i = 0; i < emailList.Count; i++)
            {
                var hasOrder = await _accountCacheManager.HasOrder(emailList[i]);
                if (!hasOrder)
                {
                    noOrderEmails.Add(emailList[i]);
                }
            }
            int userCount = noOrderEmails.Count;
            if (userCount == 0)
            {
                await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = _msgObj, Action = "已登录用户都有订单了，退出抢购", Type = Consts.ErrMsg });
                return;
            }
            int productCount = productList.Count;
            var assignedUsers = new List<string>();
            for (int i = 0; i < productCount; i++)
            {
                int idx = (_guardUserIndex + i) % userCount;
                assignedUsers.Add(noOrderEmails[idx]);
            }
            _guardUserIndex = (_guardUserIndex + productCount) % userCount;
            var tasks = productList.Select(async (p, idx) =>
            {
                var email = assignedUsers[idx];
                var input = new ShoppingInput()
                {
                    Email = email,
                    ProductName = p.Name,
                    Cart = new(){
                        new() {
                            product_id = p.Id,
                            quantity = 1
                        }
                    }
                };
                await MsgHelper.SendAsync(_hubContext, new MsgData { Obj = _msgObj, Action = $"{email}开始尝试下单商品:{p.Name}" });
                await shoppingService.TryAddBasket(input);
            });
            await Task.WhenAll(tasks);
        }
    }
}

